home *** CD-ROM | disk | FTP | other *** search
- /* ax.25 mailbox by w9nk */
- /* adapted to CHLNET environment by PE1CHL */
- /* outbound forwarding to AX.25 BBS systems added by PE1CHL */
-
- #include <stdio.h>
- #include <time.h>
- #include <ctype.h>
- #ifdef UNIX
- #include <sys/types.h>
- #endif
- #include "global.h"
- #include "mbuf.h"
- #include "ax25.h"
- #include "timer.h"
- #include "iface.h"
- #include "lapb.h"
- #include "smtp.h"
- #include "ax_mbx.h"
- #include "cmdparse.h"
-
- /* #define MBDEBUG */
-
- static char mbmenu[] = "(B)ye, (I)nfo, (S)end >\r";
- static char mbprompt[] = ">\r";
- static char mbok[] = "OK\r";
- static char mbno[] = "NO\r";
- static char mberr[] = "Huh?\r";
- static char mbserr[] = "S command syntax error - format is:\r S name [@ host] [< from_addr] [$bulletin_id]\r";
- static char mbbaduser[] = "Bad user or host name\r";
- static char mbsubject[] = "Subject:\r";
- static char mbmesg[] = "Enter message. Terminate with /EX or ^Z in first column:\r";
- static char mbtemp[] = "Can't create temp file for mail\r";
- static char mbqerr[] = "Couldn't queue message for delivery\r";
- static char mbbye[] = "Goodbye!\r";
- static char mbcr[] = "\r";
-
- extern char hostname[];
-
- char mbxinfofile[80] = "";
- static struct mbx *fwdmbx; /* currently-connecting mbx */
-
- static int mbx_line(),mbx_sid(),mbx_script();
- static void mbx_rx(),mbx_tx(),mbx_send(),mbx_doscript();
- void mbxfwd();
-
- static int dombxconnect();
- struct cmds fwdcmds[] = {
- "connect", dombxconnect, 3, NULLCHAR, NULLCHAR,
- NULLCHAR, NULLFP, 0, NULLCHAR, NULLCHAR
- };
-
- extern char *getnenv();
- extern char *strstr();
-
- /* find mbx struct for specified axp */
-
- static struct mbx *
- find_mbx(axp)
- register struct ax25_cb *axp;
- {
- register struct mbx *m;
-
- for (m = (struct mbx *) ((struct ax25_call *) axp->user)->user;
- m != NULLMBX; m = m->next) {
- if(m->ax25_cb == axp)
- break;
- }
-
- return m;
- }
-
- /* State-change upcall handler for mailbox */
-
- void
- mbx_state(axp,old,new,msg)
- register struct ax25_cb *axp;
- int old,new,msg;
-
- {
- register struct mbx *m;
- char *cp;
- struct mbxpath *mbp;
- char mesg[160];
-
- switch (new)
- {
- case CONNECTED:
- #ifdef MBDEBUG
- printf("MBX: connected\n");
- #endif
- /* check if station already known, and register if not */
- if((m = find_mbx(axp)) == NULLMBX) {
- if((m = (struct mbx *) calloc(1,sizeof(struct mbx))) == NULLMBX) {
- axp->state = DISCONNECTED; /* send DM */
- return;
- }
-
- /* connect the user to this mbox's user list */
- if((m->next = (struct mbx *) ((struct ax25_call *) axp->user)->user)
- != NULLMBX)
- m->next->prev = m;
-
- ((struct ax25_call *) axp->user)->user = (char *) m;
- m->ax25_cb = axp;
-
- pax25(m->name,&axp->addr.dest);
- cp = index(m->name,'-');
- if (cp != NULLCHAR) /* get rid of SSID */
- *cp = '\0';
- for (cp = m->name; *cp != '\0'; cp++)
- *cp = tolower(*cp); /* convert to lowercase */
-
- axp->r_upcall = mbx_rx;
- axp->t_upcall = mbx_tx;
- #ifdef MBDEBUG
- printf("MBX: new user %s\n",m->name);
- #endif
- log_ax(axp,"Conn to mbox");
-
- sprintf(mesg,"%c[NET-$]\rWelcome to the %s TCP/IP Mailbox\r%s",
- PID_FIRST|PID_LAST|PID_NO_L3,hostname,mbmenu);
-
- enqueue(&axp->txq,qstring(mesg));
- }
-
- /* send first message when script starts with "s" */
- if (m->state == MBX_CONN)
- mbx_tx(axp,1);
-
- break;
-
- case DISCONNECTED:
- if ((m = find_mbx(axp)) == NULLMBX)
- break;
-
- if(m->prev != NULLMBX)
- m->prev->next = m->next;
- else
- ((struct ax25_call *) axp->user)->user = (char *) m->next;
-
- if(m->next != NULLMBX)
- m->next->prev = m->prev;
-
- if (m->to != NULLCHAR)
- free(m->to);
-
- if (m->tofrom != NULLCHAR)
- free(m->tofrom);
-
- if (m->tomsgid != NULLCHAR)
- free(m->tomsgid);
-
- if (m->fullfrom != NULLCHAR)
- free(m->fullfrom);
-
- if (m->subject != NULLCHAR)
- free(m->subject);
-
- while (m->mbpath != NULLMBXPATH) {
- mbp = m->mbpath->next;
- free(m->mbpath);
- m->mbpath = mbp;
- }
-
- if (m->tfile != NULLFILE)
- fclose(m->tfile);
-
- if (m->script != NULLFILE)
- fclose(m->script);
-
- if (m->smtp_cb != NULLCB)
- if (m->state == MBX_DISC) { /* expecting DISC? */
- #ifdef MBDEBUG
- printf("MBX: mbx_state calls mbxfwd\n");
- #endif
- mbxfwd(m->smtp_cb); /* then, start fwd to next box */
- } else {
- #ifdef MBDEBUG
- printf("MBX: mbx_state calls del_session\n");
- #endif
- del_session(m->smtp_cb); /* no, wait a while */
- }
-
- free(m);
- break;
- }
- }
-
- /* receive upcall for ax.25 */
-
- static void mbx_rx(axp,cnt)
- struct ax25_cb *axp;
- int16 cnt;
- {
- struct mbx *m;
- struct mbuf *bp;
- char line[MBXLINE + 1];
- struct mbuf *recvl_ax25();
-
- if((m = find_mbx(axp)) == NULLMBX) {
- disc_ax25(axp); /* who are you?? */
- return;
- }
-
- while((bp = recvl_ax25(axp,0)) != NULLBUF){ /* get a line of text */
- line[pullup(&bp,line,sizeof(line) - 1)] = '\0';
- rip(line);
- free_p(bp);
- if(mbx_line(m,line) == -1) /* evaluate inputline */
- break; /* quit after "bye" */
- }
- }
-
- /* transmit upcall (used to send a file/mail) */
-
- static void
- mbx_tx(axp,cnt)
- struct ax25_cb *axp;
- int16 cnt;
- {
- struct mbx *m;
- int remain;
- char *pac;
- char line[MBXLINE + 1];
-
- if((m = find_mbx(axp)) == NULLMBX) {
- disc_ax25(axp); /* who are you?? */
- return;
- }
-
- switch (m->state)
- {
- case MBX_CONN: /* connecting? */
- case MBX_SEND: /* transferring mail? */
- mbx_doscript(m); /* keep it going */
- break;
-
- case MBX_INFO: /* sending info? */
- case MBX_BODY: /* sending mail body? */
- if (m->tfile != NULLFILE) {
- if ((remain = axp->maxframe - len_q(axp->txq)) < 2)
- pac = NULLCHAR;
- else
- if ((pac = malloc(axp->paclen)) != NULLCHAR)
- pac[0] = '\0'; /* clean packet buffer */
-
- while (fgets(line,sizeof(line),m->tfile) != NULLCHAR) {
- rip(line);
- strcat(line,mbcr);
-
- if (pac == NULLCHAR) {
- mbx_msg(m,line);
- remain--;
- } else {
- if ((strlen(pac) + strlen(line)) < axp->paclen){
- strcat(pac,line); /* still fits, concat it */
- continue; /* read next line */
- }
- if (pac[0] != '\0'){
- mbx_msg(m,pac); /* too long, flush old */
- remain--;
- }
- strcpy(pac,line);
- }
-
- /* when only one packet left in window, stop buffering */
- if (remain < 2 && pac != NULLCHAR){
- if (pac[0] != '\0'){
- mbx_msg(m,pac);
- remain--;
- }
- free(pac);
- pac = NULLCHAR;
- }
-
- if (remain <= 0)
- return; /* window full, pause */
- }
- fclose(m->tfile);
- m->tfile = NULLFILE;
-
- /* don't forget buffered packet */
- if (pac != NULLCHAR){
- if (pac[0] != '\0')
- mbx_msg(m,pac);
- free(pac);
- }
-
- /* got EOF, see what to do next. when INFO: ->command state */
- /* when BODY: send end-of-message and back to SEND state */
- if (m->state == MBX_INFO) {
- m->state = MBX_CMD;
- mbx_msg(m,(m->sid & MBX_SID) ? mbprompt : mbmenu);
- } else {
- m->state = MBX_SEND;
- if (m->sline[1] == '\0')
- strcpy(m->sline + 1,"\032"); /* default ^Z */
- strcat(m->sline,mbcr);
- mbx_msg(m,m->sline + 1);
- if (mbx_script(m) == 0)
- mbx_doscript(m);
- }
- }
- break;
- }
- }
-
- /* process one line for the mailbox */
-
- static int
- mbx_line(m,line)
- struct mbx *m;
- char *line;
- {
- switch (m->state)
- {
- case MBX_CMD:
- switch (tolower(line[0])) {
- case 'b': /* bye - bye */
- if (!(m->sid & MBX_SID))
- mbx_msg(m,mbbye);
- close_ax25(m->ax25_cb);
- return -1; /* tell line processor to quit */
-
- case 'i': { /* info */
- if (mbxinfofile[0] == '\0' ||
- (m->tfile = fopen(mbxinfofile,"r")) == NULLFILE)
- mbx_msg(m,(m->sid & MBX_SID) ? mbprompt : mbmenu);
- else {
- m->state = MBX_INFO;
- mbx_tx(m->ax25_cb,1);
- }
- }
- break;
-
- case 's': {
- int badsubj = 0;
-
- /* Get S-command type (B,P,T, etc.) */
-
- if (line[1] == '\0')
- m->stype = ' ';
- else
- m->stype = toupper(line[1]);
-
- if (mbx_to(m,line) == -1) {
- if (m->sid & MBX_SID)
- mbx_msg(m,mbno);
- else {
- mbx_msg(m,mbserr);
- }
- badsubj++;
- }
- else if (validate_address(m->to) == 0) {
- if (m->sid & MBX_SID)
- mbx_msg(m,mbno);
- else
- mbx_msg(m,mbbaduser);
- free(m->to);
- m->to = NULLCHAR;
- if (m->tofrom) {
- free(m->tofrom);
- m->tofrom = NULLCHAR;
- }
- if (m->tomsgid) {
- free(m->tomsgid);
- m->tomsgid = NULLCHAR;
- }
- badsubj++;
- }
-
- if (badsubj)
- mbx_msg(m,(m->sid & MBX_SID) ? mbprompt : mbmenu);
- else {
- m->state = MBX_SUBJ;
- mbx_msg(m,(m->sid & MBX_SID) ? mbok : mbsubject);
- }
- break;
- }
- case '[': /* SID */
- if (mbx_sid(m,line)) /* check and process it */
- goto huh; /* error, say huh */
-
- mbx_msg(m,mbprompt); /* it's okay! */
- break;
-
-
- case 'f':
- if (line[1] == '>' && (m->sid & MBX_SID)) {
- /* RLI BBS' expect us to disconnect if we */
- /* have no mail for them, which of course */
- /* we don't, being rather haughty about our */
- /* protocol superiority. */
- if (m->sid & MBX_SID_RLI) {
- close_ax25(m->ax25_cb);
- return -1;
- } else
- mbx_msg(m,mbprompt);
- break;
- }
- /* Otherwise drop through to "huh?" */
-
- huh:
- default:
- mbx_msg(m,mberr);
- mbx_msg(m,(m->sid & MBX_SID) ? mbprompt : mbmenu);
- }
- break;
-
- case MBX_SUBJ:
- if ((m->subject = malloc(strlen(line) + 1)) == NULLCHAR) {
- close_ax25(m->ax25_cb);
- return -1; /* tell line processor to quit */
- }
-
- strcpy(m->subject,line);
-
- if ((m->sid & MBX_SID) == 0)
- mbx_msg(m,mbmesg);
-
- m->state = MBX_HEAD;
- break;
-
- case MBX_HEAD:
- if (!strncmp(line,"R:",2) && strlen(line) > 14) {
- register struct mbxpath *mbp;
- register char *p;
- char *q;
-
- if ((mbp = (struct mbxpath *) calloc(1,sizeof(struct mbxpath))) == NULLMBXPATH) {
- close_ax25(m->ax25_cb);
- return -1; /* tell line processor to quit */
- }
-
- mbp->next = m->mbpath;
- m->mbpath = mbp;
-
- /* parse the "received date/time" field */
- if (isalpha(line[13])) /* timezone given? */
- mbp->z = line[13];
-
- line[13] = '\0';
- mbp->mm = atoi(&line[11]);
- line[11] = '\0';
- mbp->hh = atoi(&line[9]);
- mbp->d = atoi(&line[6]);
- line[6] = '\0';
- mbp->m = atoi(&line[4]);
- line[4] = '\0';
- mbp->y = atoi(&line[2]);
-
- /* parse the @bbs field */
- for (p = &line[14]; *p != '\0' && *p != '@'; p++)
- ;
-
- if (*p++ == '@') {
- if (*p == ':')
- p++;
- while (*p == ' ')
- p++;
- q = mbp->name;
- while (isalnum(*p) && (q - mbp->name) < 6) {
- *q++ = tolower(*p);
- p++;
- }
- }
- break;
- }
- m->state = MBX_DATA; /* no more headers, DATA state */
-
- /* generate full "from" address (return path to sender) */
- {
- char fullfrom[80];
-
- strcpy(fullfrom,(m->tofrom != NULLCHAR)? m->tofrom : m->name);
- if (m->mbpath != NULLMBXPATH && m->mbpath->next != NULLMBXPATH)
- sprintf(fullfrom + strlen(fullfrom),"%%%s",m->mbpath->name);
- sprintf(fullfrom + strlen(fullfrom),"%%%s%s@%s",
- m->name,(m->sid & MBX_SID)? ".bbs":"",hostname);
-
- if ((m->fullfrom = malloc(strlen(fullfrom) + 1)) == NULLCHAR) {
- close_ax25(m->ax25_cb);
- return -1;
- }
-
- strcpy(m->fullfrom,fullfrom);
- }
-
- if (mbx_data(m) == -1) { /* create temp & write headers */
- mbx_msg(m,mbtemp);
- close_ax25(m->ax25_cb);
- return -1;
- }
- if (line[0] == '\0') /* skip first line when empty */
- break;
-
- case MBX_DATA:
- if (line[0] == 0x1a ||
- strcmp(line,"/ex") == 0 ||
- strcmp(line,"/EX") == 0)
- {
- char *host;
-
- if ((host = index(m->to,'@')) == NULLCHAR)
- host = hostname; /* use our hostname */
- else
- host++; /* use the host part of address */
-
- fseek(m->tfile,0L,0); /* reset to beginning */
- if (queuejob(NULL,m->tfile,host,m->to,m->fullfrom) != 0)
- mbx_msg(m,mbqerr);
-
- free(m->to);
- m->to = NULLCHAR;
- free(m->fullfrom);
- m->fullfrom = NULLCHAR;
- if (m->tofrom) {
- free(m->tofrom);
- m->tofrom = NULLCHAR;
- }
- if (m->tomsgid) {
- free(m->tomsgid);
- m->tomsgid = NULLCHAR;
- }
- free(m->subject);
- m->subject = NULLCHAR;
- fclose(m->tfile);
- m->tfile = NULLFILE;
- m->state = MBX_CMD;
- mbx_msg(m,(m->sid & MBX_SID) ? mbprompt : mbmenu);
- break;
- }
- /* not done yet! */
- fprintf(m->tfile,"%s\n",line);
- break;
-
- case MBX_CONN: /* connecting a box */
- mbx_sid(m,line); /* when a SID received, note it */
- /* and process incoming data... */
- case MBX_SEND: /* sending mail */
- case MBX_BODY: /* transferring mail text */
- switch (m->sline[0]) /* look at current script op */
- {
- case 'r': /* receiving something */
- if (line[0] == '\0') /* ignore empty lines */
- break;
-
- if (strstr(line,m->sline + 1) != NULL) {
- if (mbx_script(m) == 0)
- mbx_doscript(m);
- else
- m->state = MBX_DISC;
- } else {
- if (m->state == MBX_CONN) {
- close_ax25(m->ax25_cb);
- } else {
- strcpy(m->smtp_cb->buf,line);
- logerr(m->smtp_cb);
- }
- }
- break;
-
- case 'w': /* awaiting something */
- if (strstr(line,m->sline + 1) != NULL) {
- if (mbx_script(m) == 0)
- mbx_doscript(m);
- else
- m->state = MBX_DISC;
- }
- break;
- }
- break;
- }
-
- return 0;
- }
-
- /* process the SID [BOX-VER-CAP] */
- static int
- mbx_sid(m,line)
- struct mbx *m;
- char *line;
- {
- int len = strlen(line);
-
- if (line[len - 1] == ']') { /* must be an SID */
- m->sid = MBX_SID;
-
- /* Now check to see if this is an RLI board. */
- /* As usual, Hank does it a bit differently from */
- /* the rest of the world. */
- if (len >= 5 && /* [RLI] at a minimum */
- strncmp(&line[1],"RLI",3) == 0) {
- m->sid |= MBX_SID_RLI;
- }
-
- return 0;
- }
-
- return 1; /* not an SID */
- }
-
- /* send something to the connected station */
- static
- mbx_msg(m,msg)
- struct mbx *m;
- char msg[];
- {
- int len;
- struct mbuf *bp;
-
- len = strlen(msg);
-
- if ((bp = alloc_mbuf(len+1)) == NULLBUF) {
- disc_ax25(m->ax25_cb);
- return -1;
- }
-
- bp->cnt = len + 1;
- *bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
- memcpy(bp->data+1,msg,len);
-
- send_ax25(m->ax25_cb,bp);
- return 0;
- }
-
-
- /* States for send line parser state machine */
-
- #define SKIP_CMD 1
- #define LOOK_FOR_USER 2
- #define IN_USER 3
- #define AFTER_USER 4
- #define LOOK_FOR_HOST 5
- #define IN_HOST 6
- #define AFTER_HOST 7
- #define LOOK_FOR_FROM 8
- #define IN_FROM 9
- #define AFTER_FROM 10
- #define LOOK_FOR_MSGID 11
- #define IN_MSGID 12
- #define FINAL_STATE 13
- #define ERROR_STATE 14
-
- /* Prepare the addressee. If the address is bad, return -1, otherwise
- * return 0
- */
- static
- mbx_to(m,cp)
- struct mbx *m;
- register char *cp;
- {
- int state;
- char *user,*host,*from,*msgid;
- int userlen = 0,hostlen = 0,fromlen = 0,msgidlen = 0;
-
- for (state = SKIP_CMD; state < FINAL_STATE; cp++) {
- #ifdef MBDEBUG
- printf("MBX: State is %d, char is %c\n", state, *cp);
- #endif
- switch (state) {
- case SKIP_CMD:
- if (*cp == '\0')
- state = ERROR_STATE; /* no user */
- else if (isspace(*cp))
- state = LOOK_FOR_USER;
- break;
- case LOOK_FOR_USER:
- if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
- state = ERROR_STATE; /* no user */
- else if (!isspace(*cp)) { /* found start of user */
- user = cp; /* point at start */
- userlen++; /* start counting */
- state = IN_USER;
- }
- break;
- case IN_USER:
- switch (*cp) {
- case '\0': /* found username only */
- state = FINAL_STATE;
- break;
- case '@':
- state = LOOK_FOR_HOST; /* hostname should follow */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* from name should follow */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id should follow */
- break;
- default:
- if (isspace(*cp))
- state = AFTER_USER; /* white space */
- else
- userlen++; /* part of username */
- }
- break;
- case AFTER_USER:
- switch (*cp) {
- case '\0':
- state = FINAL_STATE; /* found username only */
- break;
- case '@':
- state = LOOK_FOR_HOST; /* hostname follows */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* fromname follows */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- if (!isspace(*cp))
- state = ERROR_STATE;
- }
- break;
- case LOOK_FOR_HOST:
- switch (*cp) {
- case '\0': /* user@? */
- case '@': /* user@@ */
- case '<': /* user@< */
- case '$': /* user@$ */
- state = ERROR_STATE;
- break;
- default:
- if (!isspace(*cp)) {
- host = cp;
- hostlen++;
- state = IN_HOST;
- }
- }
- break;
- case IN_HOST:
- switch (*cp) {
- case '\0':
- state = FINAL_STATE; /* found user@host */
- break;
- case '@':
- state = ERROR_STATE; /* user@host@? */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* fromname follows */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- if (isspace(*cp))
- state = AFTER_HOST;
- else
- hostlen++;
- }
- break;
- case AFTER_HOST:
- switch (*cp) {
- case '\0':
- state = FINAL_STATE; /* user@host */
- break;
- case '@':
- state = ERROR_STATE; /* user@host @ */
- break;
- case '<':
- state = LOOK_FOR_FROM; /* user@host < */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* user@host $ */
- break;
- default:
- if (!isspace(*cp))
- state = ERROR_STATE;/* user@host foo */
- }
- break;
- case LOOK_FOR_FROM:
- switch (*cp) {
- case '\0': /* user@host <? */
- case '@': /* user@host <@ */
- case '<': /* user@host << */
- case '$': /* user@host <$ */
- state = ERROR_STATE;
- break;
- default:
- if (!isspace(*cp)) {
- from = cp;
- fromlen++;
- state = IN_FROM;
- }
- }
- break;
- case IN_FROM:
- switch (*cp) {
- case '\0':
- state = FINAL_STATE; /* user@host <foo */
- break;
- case '<':
- state = ERROR_STATE; /* user@host <foo< */
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* message id follows */
- break;
- default:
- if (isspace(*cp))
- state = AFTER_FROM;
- else
- fromlen++;
- }
- break;
- case AFTER_FROM:
- switch (*cp) {
- case '\0':
- state = FINAL_STATE; /* user@host <foo */
- break;
- case '@': /* user@host <foo @ */
- case '<': /* user@host <foo < */
- state = ERROR_STATE;
- break;
- case '$':
- state = LOOK_FOR_MSGID; /* user@host <foo $ */
- break;
- default:
- if (!isspace(*cp))
- state = ERROR_STATE;/* user@host foo */
- }
- break;
- case LOOK_FOR_MSGID:
- if (*cp == '\0')
- state = ERROR_STATE; /* msgid = $? */
- else if (isspace(*cp))
- state = ERROR_STATE; /* user@host <foo $ bar */
- else {
- msgid = cp;
- msgidlen++;
- state = IN_MSGID;
- }
- break;
- case IN_MSGID:
- if (*cp == '\0')
- state = FINAL_STATE;
- else if (isspace(*cp))
- state = FINAL_STATE;
- else
- msgidlen++;
- break;
- default:
- /* what are we doing in this state? */
- state = ERROR_STATE;
- }
- }
-
- if (state == ERROR_STATE)
- return -1; /* syntax error */
-
- if ((m->to = malloc(userlen + hostlen + 2)) == NULLCHAR)
- return -1; /* no room for to address */
-
- strncpy(m->to,user,userlen);
- m->to[userlen] = '\0';
-
- if (hostlen) {
- m->to[userlen] = '@';
- strncpy(m->to + userlen + 1,host,hostlen);
- m->to[userlen + hostlen + 1] = '\0';
- }
-
- for (cp = m->to; *cp != '\0'; cp++)
- *cp = tolower(*cp);
-
- if (fromlen) {
- if ((m->tofrom = malloc(fromlen + 1)) == NULLCHAR) {
- free(m->to);
- m->to = NULLCHAR;
- return -1;
- }
- strncpy(m->tofrom,from,fromlen);
- m->tofrom[fromlen] = '\0';
-
- for (cp = m->tofrom; *cp != '\0'; cp++)
- *cp = tolower(*cp);
- }
-
- if (msgidlen) {
- if ((m->tomsgid = malloc(msgidlen + 1)) == NULLCHAR) {
- free(m->to);
- m->to = NULLCHAR;
- if (fromlen) {
- free(m->tofrom);
- m->tofrom = NULLCHAR;
- }
- return -1;
- }
- strncpy(m->tomsgid,msgid,msgidlen);
- m->tomsgid[msgidlen] = '\0';
- }
-
- return 0;
- }
-
- /* This opens the data file and writes the mail header into it.
- * Returns 0 if OK, and -1 if not.
- */
-
- static
- mbx_data(m)
- struct mbx *m;
- {
- time_t t;
- long m_id;
- int i;
- struct mbxpath *mbp;
- char *ptime(),*pxtime();
- extern FILE *tmpfile();
- extern long get_msgid();
-
- if ((m->tfile = tmpfile()) == NULLFILE)
- return -1;
-
- time(&t);
- fprintf(m->tfile,"Received: from %s%s by %s with %s\n\tid AA%ld ; %s",
- m->name,(m->sid & MBX_SID)? ".bbs":"",
- hostname,(m->sid & MBX_SID)? "BBSFWD":"AX25",
- m_id = get_msgid(),ptime(&t));
- fprintf(m->tfile,"Date: %s",m->mbpath == NULLMBXPATH?
- ptime(&t) :
- pxtime(m->mbpath->y,m->mbpath->m,m->mbpath->d,
- m->mbpath->hh,m->mbpath->mm,m->mbpath->z));
- if (m->tomsgid != NULLCHAR)
- fprintf(m->tfile,"Message-Id: <%s@%s>\n",m->tomsgid,hostname);
- else
- fprintf(m->tfile,"Message-Id: <%ld@%s>\n",m_id,hostname);
- fprintf(m->tfile,"From: %s\n",m->fullfrom);
- fprintf(m->tfile,"To: %s\n",m->to);
- fprintf(m->tfile,"Subject: %s\n",m->subject);
- if (m->stype != ' ')
- fprintf(m->tfile,"X-BBS-Msg-Type: %c\n",m->stype);
- if (m->mbpath != NULLMBXPATH) {
- if (m->mbpath->next == NULLMBXPATH) {
- free(m->mbpath);
- m->mbpath = NULLMBXPATH;
- } else {
- fprintf(m->tfile,"X-BBS-Path: ");
- i = 0;
- while (m->mbpath != NULLMBXPATH) {
- fprintf(m->tfile,"%s",m->mbpath->name);
- mbp = m->mbpath->next;
- free(m->mbpath);
- m->mbpath = mbp;
- if (m->mbpath != NULLMBXPATH) {
- if (++i > 8) {
- fprintf(m->tfile,"\n\t\t");
- i = 0;
- } else {
- fprintf(m->tfile,"!");
- }
- }
- }
- fprintf(m->tfile,"\n");
- }
- }
- fprintf(m->tfile,"\n"); /* blank line before message body */
-
- return 0;
- }
-
- /* forward jobs to specified AX.25 mailboxes */
- void
- mbxfwd(cb)
- struct smtp_cb *cb;
- {
- FILE *script;
- char tmp[MBXLINE];
-
- if (cb->jobq != NULLJOB) do
- {
- #ifdef MBDEBUG
- printf("MBX: AX.25 forward to %s\n",cb->jobq->system);
- #endif
- sprintf(tmp,"%s%s",getnenv(MAILQDIR),cb->jobq->system);
- if ((script = fopen(tmp,"r")) == NULL)
- continue;
-
- /* read the initial connection line (skip comments) */
- do
- {
- if (fgets(tmp,MBXLINE,script) == NULL)
- tmp[0] = '\0';
-
- rip(tmp);
- } while (tmp[0] == '#');
-
- #ifdef MBDEBUG
- printf("MBX: attempt %s\n",tmp);
- #endif
-
- if (cmdparse(fwdcmds,tmp)) { /* attempt a connect */
- #ifdef MBDEBUG
- printf("MBX: connect failed\n");
- #endif
- fclose(script);
- continue; /* it failed, try next */
- }
-
- fwdmbx->smtp_cb = cb; /* set values in mbx struct */
- fwdmbx->script = script;
-
- if (mbx_script(fwdmbx) != 0) /* read next script line */
- continue;
-
- fwdmbx = NULLMBX; /* prevent mis-use */
- return; /* wait for connection */
- }
- while (nextjob(cb)); /* some error, try next job */
-
- #ifdef MBDEBUG
- printf("MBX: mbxfwd calls del_session\n");
- #endif
- del_session(cb); /* all jobs failed */
- }
-
- /* read next connection/mailing script line */
- static int
- mbx_script (m)
- register struct mbx *m;
-
- {
- do
- {
- if (fgets(m->sline,MBXLINE,m->script) == NULL) {
- #ifdef MBDEBUG
- printf("MBX script: EOF\n");
- #endif
- m->sline[0] = '\0';
- if (m->state != MBX_DISC)
- close_ax25(m->ax25_cb); /* terminate connection */
- m->state = MBX_DISC; /* we expect a disconnect */
- return 1;
- }
- rip(m->sline);
- } while (m->sline[0] == '\0' || m->sline[0] == '#');
-
- #ifdef MBDEBUG
- printf("MBX script: %s\n",m->sline);
- #endif
- return 0;
- }
-
- /* interpret current script line and send output */
-
- static void
- mbx_doscript (m)
- register struct mbx *m;
-
- {
- char *p;
- struct list *lp;
- int d;
- static char type[] = "P";
- char line[80],tmp[80];
-
- #ifdef MBDEBUG
- printf("MBX do_script: %s\n",m->sline);
- #endif
-
- switch (m->sline[0]) /* first char is opcode */
- {
- case 'b': /* send mail body */
- m->state = MBX_BODY;
- mbx_tx(m->ax25_cb,1); /* kick off */
- break;
-
- case 'l': /* loopback point for mail */
- m->state = MBX_SEND;
- m->mpos = ftell(m->script);
- mbx_script(m);
- mbx_send(m); /* send the message */
- break;
-
- case 'm': /* send a mail message */
- /* make sure we have a message-id. use job-id when not avail. */
- if (m->tomsgid == NULLCHAR) {
- sprintf(tmp,"%s_%s",m->smtp_cb->jobq->jobname,hostname);
- if ((m->tomsgid = malloc(strlen(tmp) + 1)) != NULLCHAR)
- strcpy(m->tomsgid,tmp);
- }
- /* filter some characters likely to be magic */
- for (p = m->tomsgid; *p != '\0'; p++)
- if (index("\"$'();<=>?@[]`{}",*p) != NULLCHAR)
- *p = '_';
-
- /* make sure we have a "from:" address */
- if (m->tofrom == NULLCHAR) {
- if ((m->tofrom = malloc(strlen(m->smtp_cb->jobq->from) + 1)) != NULLCHAR)
- strcpy(m->tofrom,m->smtp_cb->jobq->from);
- }
-
- /* scan "from:", probably of form "rob@pe1chl" or "pe1chl@pe1chl" */
- /* we want to extract a callsign from this, which is not easy! */
- /* first, examine the part before the @ sign */
- d = 0;
- for (p = m->tofrom; *p != '\0'; p++) {
- if (!isalnum(*p))
- break;
- if (isdigit(*p)) /* count digits */
- d++;
- }
- /* when we got a digit we probably have a callsign */
- /* when not, look further but watch out for things like: */
- /* "rob@sys2.pe1chl". in this case, skip the first part */
- while (d == 0) {
- if (p[0] == '\0' || p[1] == '\0') /* more coming? */
- break; /* no, use what we have now */
-
- strcpy(m->tofrom,p + 1); /* shift left */
-
- for (p = m->tofrom; *p != '\0'; p++) {
- if (!isalnum(*p)) { /* next separator */
- if (!isdigit(p[-1])) /* hack! trap "sys2.pe1chl"-like */
- d++; /* break from outer loop */
- break;
- }
- }
- }
- *p = '\0'; /* terminate what we have */
-
- /* process the destination address. we want call and bbs in */
- /* separate fields to be able to massage them in the script */
- strcpy(tmp,m->smtp_cb->jobq->to->val);
- if ((p = rindex(tmp,'@')) != NULLCHAR)
- *p = '\0'; /* chop off @xxxxxx.bbs */
- if ((p = index(tmp,'%')) != NULLCHAR) {
- *p++ = '\0';
- } else {
- strcpy(p = tmp + 40,m->smtp_cb->jobq->system);
- if ((p = index(p,'.')) != NULLCHAR)
- *p = '\0';
- p = tmp + 40;
- }
-
- /* make a message type. a string allows more flexibility */
- type[0] = m->stype;
-
- /* now, create the "send" command from script and args */
- strcat(m->sline,mbcr);
- sprintf(line,m->sline + 1,type,tmp,p,m->tofrom,m->tomsgid,NULL,NULL);
- mbx_msg(m,line);
- mbx_script(m);
- break;
-
- case 'n': /* next mail */
- log_ax(m->ax25_cb,"MBX sent job %s To: %s From: %s",
- m->smtp_cb->jobq->jobname,
- m->smtp_cb->jobq->to->val,
- m->smtp_cb->jobq->from);
-
- /* drop this recepient and check if more */
- lp = m->smtp_cb->jobq->to->next;
- free(m->smtp_cb->jobq->to);
- if ((m->smtp_cb->jobq->to = lp) != NULLLIST && m->mpos != 0) {
- fseek(m->script,m->mpos,0); /* back to loopback point */
- mbx_script(m);
- mbx_send(m);
- break;
- }
-
- if (m->smtp_cb->errlog != NULLLIST)
- retmail(m->smtp_cb); /* return mail when error */
-
- unlink(m->smtp_cb->tname); /* unlink textfile */
- unlink(m->smtp_cb->wname); /* unlink workfile */
-
- /* check if next job happens to be addressed to same system */
- strcpy(tmp,m->smtp_cb->jobq->system);
- if (nextjob(m->smtp_cb) && !strcmp(tmp,m->smtp_cb->jobq->system) && m->mpos != 0) {
- fseek(m->script,m->mpos,0); /* back to loopback point */
- mbx_script(m);
- mbx_send(m);
- break;
- }
-
- mbx_script(m); /* no, continue script */
- mbx_doscript(m); /* (it will log-off the box) */
- break;
-
- case 's': /* send a string */
- strcat(m->sline,mbcr);
- mbx_msg(m,m->sline + 1);
- mbx_script(m);
- break;
-
- case 'u': /* send subject */
- strcat(m->sline,mbcr);
- sprintf(line,m->sline + 1,m->subject != NULLCHAR? m->subject : "",NULL,NULL);
- mbx_msg(m,line);
- mbx_script(m);
- break;
- }
- }
-
- /* send a message to the (already connected) ax.25 mailbox */
- static void
- mbx_send (m)
- register struct mbx *m;
- {
- register char *p;
- struct list *lp;
- int n = 'A' - 1;
- char line[MBXLINE];
- char *getname();
-
- if (m->subject != NULLCHAR)
- free(m->subject);
- m->subject = NULLCHAR;
-
- if (m->tofrom != NULLCHAR)
- free(m->tofrom);
- m->tofrom = NULLCHAR;
-
- if (m->tomsgid != NULLCHAR)
- free(m->tomsgid);
- m->tomsgid = NULLCHAR;
- m->stype = 'P';
-
- /* open message and read headers to get some reqd info */
-
- if ((m->tfile = fopen(m->smtp_cb->tname,"r")) == NULLFILE) {
- close_ax25(m->ax25_cb); /* too many files? */
- return; /* try again later */
- }
-
- while (fgets(line,MBXLINE,m->tfile) != NULL) {
- rip(line);
- if (line[0] == '\0') /* empty line ends headers */
- break;
-
- if (!strncasecmp(line,"subject:",8)) {
- if (m->subject != NULLCHAR)
- free(m->subject);
-
- for (p = line + 8; *p == ' '; p++)
- ;
-
- if ((m->subject = malloc(strlen(p) + 1)) != NULLCHAR)
- strcpy(m->subject,p);
-
- #ifdef MBDEBUG
- printf("MBX: subject %s\n",m->subject);
- #endif
- continue;
- }
-
- if (!strncasecmp(line,"from:",5)) {
- if (m->tofrom != NULLCHAR)
- free(m->tofrom);
-
- for (p = line + 5; *p == ' '; p++)
- ;
-
- if ((m->tofrom = malloc(strlen(p) + 1)) != NULLCHAR)
- strcpy(m->tofrom,p);
-
- #ifdef MBDEBUG
- printf("MBX: from %s\n",m->tofrom);
- #endif
- continue;
- }
-
- if (!strncasecmp(line,"message-id:",11)) {
- if (m->tomsgid != NULLCHAR) {
- free(m->tomsgid);
- m->tomsgid = NULLCHAR;
- }
-
- if ((p = getname(line)) != NULLCHAR) {
- if ((m->tomsgid = malloc(strlen(p) + 2)) != NULLCHAR) {
- /* when multiple recepients, generate unique msgid */
- if ((lp = m->smtp_cb->jobq->to->next) != NULLLIST) {
- while (lp != NULLLIST) {
- n++;
- lp = lp->next;
- }
-
- m->tomsgid[0] = n; /* A B C... */
- m->tomsgid[1] = '\0';
- } else
- m->tomsgid[0] = '\0';
-
- strcat(m->tomsgid,p); /* plus org id */
- }
-
- #ifdef MBDEBUG
- printf("MBX: message-id %s\n",m->tomsgid);
- #endif
- }
-
- continue;
- }
-
- if (!strncasecmp(line,"x-bbs-msg-type:",15)) {
- for (p = line + 15; *p == ' '; p++)
- ;
-
- m->stype = *p;
-
- #ifdef MBDEBUG
- printf("MBX: message type %c\n",m->stype);
- #endif
- continue;
- }
- }
-
- fseek(m->tfile,0L,0); /* rewind to beginning */
- mbx_doscript(m); /* start the message xfer */
- }
-
- static int
- dombxconnect (argc,argv)
- int argc;
- char *argv[];
- {
- struct ax25 addr;
- struct ax25_cb *open_ax25();
- register struct ax25_call *axc;
- register struct mbx *m;
- struct interface *ifp;
- extern int16 axwindow;
- int i;
- struct ax25_cb *find_ax25();
-
- if((ifp = if_lookup(argv[1])) == NULLIF)
- return 1;
-
- if(!(ifp->flags & IF_AX25))
- return 1;
-
- memset(&addr,0,sizeof(addr));
- if(setcall(&addr.dest,argv[2]) < 0)
- return 1;
-
- /* Find the MBX call on this interface */
- for (axc = ax25_port; axc != NULLAXCALL; axc = axc->p_next){
- if(axc->port == MBOXPORT &&
- ((axc->flags & MULTI_IF) || axc->interface == ifp)){
- ASSIGN(addr.source,axc->addr);
- break;
- }
- }
- if (axc == NULLAXCALL)
- return 1;
-
- /* Check if already connected to that station */
- if(find_ax25(&addr.dest,&addr.source) != NULLAX25) {
- #ifdef MBDEBUG
- printf("MBX: already connected!\n");
- #endif
- return 1;
- }
-
- /* Set digipeater path */
- if((addr.ndigis = argc - 3) > MAXDIGIS)
- return 1;
- for(i=3; i < argc; i++)
- if(setcall(&addr.digis[i-3],argv[i]) < 0)
- return 1;
-
- if((m = (struct mbx *) calloc(1,sizeof(struct mbx))) == NULLMBX)
- return 1;
-
- /* connect the user to this mbox's user list */
- if((m->next = (struct mbx *) axc->user) != NULLMBX)
- m->next->prev = m;
-
- axc->user = (char *) m;
-
- m->state = MBX_CONN;
- fwdmbx = m; /* keep forwarded mbx */
-
- #ifdef MBDEBUG
- printf("MBX: calling open_ax25 for %lx\n",m);
- #endif
- if ((m->ax25_cb = open_ax25(&addr,axwindow,mbx_rx,mbx_tx,mbx_state,
- ifp,(char *)axc)) == NULLAX25){
- if(m->next != NULLMBX)
- m->next->prev = NULLMBX;
-
- axc->user = (char *) m->next;
- free(m);
- return 1;
- }
-
- /* set a reasonable value for the idle-link disconnect time */
- if (m->ax25_cb->t4.start == 0 || TICK2SEC(m->ax25_cb->t4.start) > 1000)
- m->ax25_cb->t4.start = SEC2TICK(300);
-
- return 0;
- }
-
-